#include "stdafx.h"
#include "MeshPart.h"

#include "VertexStream.h"

namespace WindGE
{
	MeshPart::MeshPart()
	{
	}

	MeshPart::~MeshPart()
	{
	}

	bool MeshPart::init_vertex_stream(const std::string& name, unsigned int stride, unsigned int count)
	{
		auto iter = stream_mapping_.find(name);
		if (iter == stream_mapping_.end())
		{
			VertexStreamPtr vstream = std::make_shared<VertexStream>();
			if (!vstream->init(name, stride, count)) return false;
			stream_mapping_.insert({ name, vstream });
		}
		else
		{
			//XdPrint("Create Failed, %s is exsist.\n", name.c_str());
			return false;
		}

		return true;
	}

	bool MeshPart::reinit_vertex_stream(const std::string& name, unsigned int num)
	{
		auto iter = stream_mapping_.find(name);
		if (iter != stream_mapping_.end())
		{
			return iter->second->reinit(num);
		}
		else
		{
			//XdPrint("Vertex stream %s not found.\n", name);
			return false;
		}
	}

	void MeshPart::add_vertex_stream(const std::string& name, void* vertBuff)
	{
		auto iter = stream_mapping_.find(name);
		if (iter != stream_mapping_.end())
		{
			iter->second->add(vertBuff);
		}
		else
		{
			//XdPrint("Vertex stream %s not found.\n", name);
		}
	}

	void MeshPart::add_vertex_stream(const std::string& name, void* vertBuff, unsigned int num)
	{
		auto iter = stream_mapping_.find(name);
		if (iter != stream_mapping_.end())
		{
			iter->second->add(vertBuff, num);
		}
		else
		{
			//XdPrint("Vertex stream %s not found.\n", name);
		}
	}

	void MeshPart::set_vertex_stream(const std::string& name, void* vertBuff, unsigned int offset)
	{
		auto iter = stream_mapping_.find(name);
		if (iter != stream_mapping_.end())
		{
			iter->second->set(vertBuff, offset);
		}
		else
		{
			//XdPrint("Vertex stream %s not found.\n", name);
		}
	}

	void MeshPart::set_vertex_stream(const std::string& name, void* vertBuff, unsigned int offset, unsigned int num)
	{
		auto iter = stream_mapping_.find(name);
		if (iter != stream_mapping_.end())
		{
			iter->second->set(vertBuff, offset, num);
		}
		else
		{
			//XdPrint("Vertex stream %s not found.\n", name);
		}
	}

	bool MeshPart::save(std::ostream& outFile)
	{
		//write vertex offset
		outFile.write((char*)&part_info_, sizeof(part_info_));

		//write vertex stream count
		unsigned int streamCount = stream_mapping_.size();
		outFile.write((char*)&streamCount, sizeof(streamCount));

		//write vertex stream
		for (auto iter = stream_mapping_.begin(); iter != stream_mapping_.end(); ++iter)
		{
			if (!iter->second->save(outFile)) return false;
		}
		return true;
	}

	bool MeshPart::load(std::istream& inFile)
	{
		//read vertex offset
		inFile.read((char*)&part_info_, sizeof(part_info_));

		//read vertex stream count
		unsigned int streamCount = 0;
		inFile.read((char*)&streamCount, sizeof(streamCount));
		
		//read vertex stream
		for (unsigned int i = 0; i < streamCount; ++i)
		{
			VertexStreamPtr vstream = std::make_shared<VertexStream>();
			if (!vstream->load(inFile)) return false;

			stream_mapping_.insert({ vstream->name(), vstream });
		}
		return true;
	}

	void MeshPart::add(VertexStreamPtr vertexStream)
	{
		auto iter = stream_mapping_.find(vertexStream->name());
		if (iter != stream_mapping_.end())
		{
			stream_mapping_[iter->first] = vertexStream;
		}
		else
		{
			stream_mapping_.insert({ vertexStream->name(), vertexStream });
		}
	}

	void MeshPart::add(const VertexStream& vertexStream)
	{
		auto iter = stream_mapping_.find(vertexStream.name());
		VertexStreamPtr newvstream = std::make_shared<VertexStream>(vertexStream);
		if (iter != stream_mapping_.end())
		{
			stream_mapping_[iter->first] = newvstream;
		}
		else
		{
			stream_mapping_.insert({ vertexStream.name(), newvstream });
		}
	}

	bool MeshPart::find(const std::string& name, VertexStreamPtr& vs) const
	{
		auto iter = stream_mapping_.find(name);
		if (iter != stream_mapping_.end())
		{
			vs = iter->second;
			return true;
		}
		vs = VertexStreamPtr(nullptr);
		return false;
	}

	void MeshPart::visit_stream_mapping(std::function<void (VertexStreamPair)> func) const
	{
		std::for_each(stream_mapping_.begin(), stream_mapping_.end(), func);
	}

}//end namespace WindGE


